﻿#ifndef __SS_3dMATH_DEF_H__
#define __SS_3dMATH_DEF_H__
#include "../ss3dDefine.h"
#include <math.h>

namespace StarSeeker
{
namespace Math3D
{

const ssfloat gc_PI = (ssfloat)3.141592654;				//派
const ssfloat gc_DOUBLE_PI = (ssfloat)6.283185308;		//2派
const ssfloat gc_HALF_PI = (ssfloat)1.570796327;		//1/2派
const ssfloat gc_QUARTER_PI = (ssfloat)0.785398164;		//1/4派
const ssfloat gc_OVER180_PI = (ssfloat)0.01745329252;	//1/180派
const ssfloat gc_180DIVIDED_PI = (ssfloat)57.29577950;	//180/派
const ssfloat gc_EPSILON_E4 = (ssfloat)1E-4;			//float允许误差,4位小数
const ssfloat gc_EPSILON_E5 = (ssfloat)1E-5;			//float允许误差,5位小数
const ssfloat gc_EPSILON_E6 = (ssfloat)1E-6;			//float允许误差,6位小数
const ssfloat gc_EPSILON_E8 = (ssfloat)1E-8;			//float允许误差,8位小数

//余弦和正弦表：0到360度
#ifdef SS_USE_TRIGONOMETRIC_TABLE
float *g_sin = 0;
float *g_cos = 0;
inline void BuildTrigonometricTable()
{
	if (g_sin || g_cos) return;

	g_sin = new float[361];
	g_cos = new float[361];
	for (short i=0; i<361; ++i)
	{
		g_sin[i] = sinf((float)i/180.0f*SS3D_PI);
		g_cos[i] = cosf((float)i/180.0f*SS3D_PI);
	}
}
#endif

inline ssfloat Abs(ssfloat fValue)
{
	return (ssfloat)::fabs(fValue);
}

inline i32 Floor(ssfloat fValue)
{
	return (i32)::floor(fValue);
}

inline i32 Ceil(ssfloat fValue)
{
	return (i32)::ceil(fValue);
}

inline ssfloat Sqrt(ssfloat fValue)
{
	return (ssfloat)::sqrt(fValue);
}

inline ssfloat Sqr(ssfloat fValue)
{
	return fValue*fValue;
}

inline ssfloat Sin(ssfloat fValue)
{
	return (ssfloat)::sin(fValue);
}

inline ssfloat Cos(ssfloat fValue)
{
	return (ssfloat)::cos(fValue);
}

inline ssfloat Tan(ssfloat fValue)
{
	return (ssfloat)::tan(fValue);
}

inline ssfloat Cot(ssfloat fValue)
{
	return (ssfloat)(1.0/::tan(fValue));
}

inline ssfloat ASin(ssfloat fValue)
{
	return (ssfloat)::asin(fValue);
}

inline ssfloat ACos(ssfloat fValue)
{
	return (ssfloat)::acos(fValue);
}

inline ssfloat ATan(ssfloat fValue)
{
	return (ssfloat)::atan(fValue);
}

inline ssfloat ATan2(ssfloat fValue1, ssfloat fValue2)
{
	return (ssfloat)::atan2(fValue1, fValue2);
}

inline ssfloat ACot(ssfloat fValue)
{
	return (ssfloat)(1.570796327-::atan(fValue));
}

//float取反
inline void AgainstFloat(f32 *pf)
{
	((unsigned char*)pf)[3] ^= 128;
}
//角度转弧度
inline ssfloat Degrees2Radian(ssfloat fDegrees)
{
	return (fDegrees * gc_OVER180_PI);
}
//弧度转角度
inline ssfloat Radian2Degrees(ssfloat fRadian)
{
	return (fRadian * gc_180DIVIDED_PI);
}

}

struct ssFLOAT2
{
	union
	{
		ssfloat m[2];
		struct { ssfloat x, y; };
	};
};
struct ssFLOAT3
{
	union
	{
		ssfloat m[3];
		struct { ssfloat x, y, z; };
		struct { ssfloat r, g, b; };
	};
};
struct ssFLOAT4
{
	union
	{
		ssfloat m[4];
		struct { ssfloat x, y, z, w; };
		struct { ssfloat r, g, b, a; };
	};
};
struct ssFLOAT2x2
{
	union
	{
		struct {
			ssfloat _11, _12,
					_21, _22;
		};
		ssfloat m2[2][2];
		ssfloat m[4];
	};
};
struct ssFLOAT3x3
{
	union
	{
		struct {
			ssfloat _11, _12, _13,
					_21, _22, _23,
					_31, _32, _33;
		};
		ssfloat m2[3][3];
		ssfloat m[9];
	};
};
struct ssFLOAT4x4
{
	union
	{
		struct {
			ssfloat _11, _12, _13, _14,
					_21, _22, _23, _24,
					_31, _32, _33, _34,
					_41, _42, _43, _44;
		};
		ssfloat m2[4][4];
		ssfloat m[16];
	};
};
struct ssFLOAT4x3
{
	union
	{
		struct {
			ssfloat _11, _12, _13,
					_21, _22, _23,
					_31, _32, _33,
					_41, _42, _43;
		};
		ssfloat m2[4][3];
		ssfloat m[12];
	};
};
struct ssViewPort
{
	union
	{
		struct {
			i32 x, y, width, height;
		};
		i32 m[4];
	};
};

#define ZERO_E4(x) (((x)>0?(x):-(x))<StarSeeker::Math3D::gc_EPSILON_E4)
#define ZERO_E5(x) (((x)>0?(x):-(x))<StarSeeker::Math3D::gc_EPSILON_E5)
#define ZERO_E6(x) (((x)>0?(x):-(x))<StarSeeker::Math3D::gc_EPSILON_E6)
#define ZERO_E8(x) (((x)>0?(x):-(x))<StarSeeker::Math3D::gc_EPSILON_E8)

}
#endif
